/*
	Copyright (c) 2007, ANYwebcam.com Pty Ltd. All rights reserved.

	The software in this package is published under the terms of the BSD style 
	license, a copy of which has been included with this distribution in the 
	license.txt file.
*/
package com.anywebcam.di.component
{
	import com.anywebcam.di.*;
	import com.anywebcam.di.component.*;
	import com.anywebcam.di.error.*;
	import com.anywebcam.reflection.ClassInfo;
	import com.anywebcam.reflection.MethodInfo;

	import flash.errors.*;
	import flexunit.framework.TestCase;
	import flexunit.framework.TestSuite;

	public class AbstractComponentTest extends TestCase
	{
		public static function suite():TestSuite
		{
			var ts:TestSuite = new TestSuite();

			var tests:Array = 
			[
				'shouldReturnClassKeyAndImplTypeAsSetInConstructor',
				'shouldReturnStringKeyAndImplTypeAsSetInConstructor',
				'shouldReturnClassInfoForSetType',
				'shouldComplainIfClassKeyAndImplTypeAreIncompatible',
				'shouldComplainOnGetInstance'
			];

			tests.forEach( function( methodName:String, index:int, array:Array ):void
			{
				ts.addTest( new AbstractComponentTest( methodName ) );
			});

			return ts;
		}

		public function AbstractComponentTest( method:String )
		{
			super( method );
		}
		
		public function shouldReturnClassKeyAndImplTypeAsSetInConstructor():void
		{
			var component:DIComponent = new AbstractComponent( ClassWithoutConstructorDependencies, ClassWithoutConstructorDependencies );
			
			assertEquals( 'Expecting ClassWithoutConstructorDependencies', ClassWithoutConstructorDependencies, component.key );
			assertEquals( 'Expecting ClassWithoutConstructorDependencies', ClassWithoutConstructorDependencies, component.type );
		}
		
		public function shouldReturnStringKeyAndImplTypeAsSetInConstructor():void
		{
			var component:DIComponent = new AbstractComponent( 'no-dependencies', ClassWithoutConstructorDependencies );
			
			assertEquals( 'Expecting "no-dependencies"', 'no-dependencies', component.key );
			assertEquals( 'Expecting ClassWithoutConstructorDependencies', ClassWithoutConstructorDependencies, component.type );
		}
		
		public function shouldReturnClassInfoForSetType():void
		{
			var component:DIComponent = new AbstractComponent( 'class-info-test', ClassWithSetters );
			
			assertNotNull( 'Expecting ClassInfo instance', component.classInfo );
			assertTrue( 'Expecting classInfo to return a ClassInfo instance', component.classInfo is ClassInfo );
		}
		
		public function shouldComplainIfClassKeyAndImplTypeAreIncompatible():void
		{
			try
			{
				var component:DIComponent = new AbstractComponent( String, Array );
				
				fail( 'AbstractComponent should complain if the Class Key and Implementation Class are incompatible' );
			}
			catch( e:DIComponentError ) {}
		}
		
		public function shouldComplainOnGetInstance():void
		{
			var component:DIComponent = new AbstractComponent( 'get-instance-test', ClassWithSetters );
			
			try
			{
				component.getInstance( null );
				
				fail( 'AbstractComponent must not implement getInstance' );
			}
			catch( e:IllegalOperationError ){}
		}
	}
}

